#region File Description
//-----------------------------------------------------------------------------
// RhythmCometGame.cs
//
// Microsoft XNA Community Game Platform
// Copyright (C) Microsoft Corporation. All rights reserved.
//-----------------------------------------------------------------------------
#endregion

#region Using Statements
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using RhythmComet.Utils;
using FMOD;
using RhythmComet.Gameplay;
using RhythmComet.Services;
#endregion

namespace RhythmComet
{
    public class RhythmCometGame : Microsoft.Xna.Framework.Game
    {
        #region Fields and Properties

        private GraphicsDeviceManager graphics;
        private SpriteBatch spriteBatch;
        private SpriteFont arialFont;
        private Comet comet;
        private GameScore score;
        private ObstacleManager obstacleManager;
        private Camera camera;
        private FPSProbe fpsProbe;
        private FrameBurst frameBurst;
#if !XBOX
        private Mp3Player player;
        private SpectrumAnalyzer spectrumAnalyzer;
#endif
        private IBeatManager beatManager;
        private InputHandler input;
        private ITitleIntroState titleIntroState;
        private IPlayingState playingState;
        private IPausedMenuState pausedMenuState;
        private IStartMenuState startMenuState;
        private IRetryMenuState retryMenuState;
        private IInstructionsState instructionsState;
        private ISongOverState songOverState;
        private GameStateManager gameManager;

        public Comet Comet
        {
            get { return comet; }
        }

        public ITitleIntroState TitleIntroState
        {
            get { return titleIntroState; }
        }

        public IPlayingState PlayingState
        {
            get { return playingState; }
        }

        public IPausedMenuState PausedMenuState
        {
            get { return pausedMenuState; }
        }

        public IStartMenuState StartMenuState
        {
            get { return startMenuState; }
        }

        public IRetryMenuState RetryMenuState
        {
            get { return retryMenuState; }
        }

        public IInstructionsState InstructionsState
        {
            get { return instructionsState; }
        }

        public ISongOverState SongOverState
        {
            get { return songOverState; }
        }

        public IBeatManager BeatManager
        {
            get { return beatManager; }
        }
#if !XBOX
        public Mp3Player Player
        {
            get { return player; }
        }
#endif

        public GraphicsDeviceManager Graphics
        {
            get { return graphics; }
        }

        public Camera Camera
        {
            get { return camera; }
        }

        public SpriteBatch SpriteBatch
        {
            get { return spriteBatch; }
        }

        public InputHandler Input
        {
            get { return input;}
        }

        public GameScore Score
        {
            get { return score; }
            set { score = value; }
        }
#if !XBOX
        public SpectrumAnalyzer SpectrumAnalyzer
        {
            get { return spectrumAnalyzer; }
        }
#endif

        public FrameBurst FrameBurst
        {
            get { return frameBurst; }
        }

        public ObstacleManager ObstacleManager
        {
            get { return obstacleManager; }
            set { obstacleManager = value; }
        }

        #endregion

        #region Constructor and Initialization

        public RhythmCometGame()
        {
            graphics = new GraphicsDeviceManager(this);
#if !XBOX
            graphics.PreferredBackBufferWidth = 853;
            graphics.PreferredBackBufferHeight = 480;
#else
            graphics.PreferredBackBufferWidth = 853;
            graphics.PreferredBackBufferHeight = 480;
#endif
            Window.Title = "Beat'n Strike";
           
        }

        protected override void Initialize()
        {
            Content.RootDirectory = "Content";
#if !XBOX
            float aspectRatio = 853.0f / 480.0f;
#else
            float aspectRatio = 853.0f / 480.0f;
#endif
            Vector3 camPosition = new Vector3(0, 0, 490);
            Vector3 camTarget = Vector3.Zero;
            Vector3 camUpVector = Vector3.Up;
            camera = new Camera(this, camTarget, camPosition, camUpVector, aspectRatio);

            score = new GameScore();
            fpsProbe = new FPSProbe();
#if !XBOX
            player = new Mp3Player();
#endif

            input = new InputHandler(this);
            Components.Add(input);

            comet = new Comet(this);
            Components.Add(comet);
            comet.Enabled = false;
            comet.Visible = false;

            obstacleManager = new ObstacleManager(this, 400, comet);
            Components.Add(obstacleManager);
            obstacleManager.Enabled = false;
            obstacleManager.Visible = false;
#if !XBOX
            beatManager = new fmodBeatDetectorManager(this, 10);
#else
            beatManager = new RandomBeatManager(this);
#endif
            beatManager.AddBand(0, 1, 3.5f, 0.25f, 1.0f);      // Subbass area
            beatManager.AddBand(1, 3, 1.3f, 0.15f, 1.0f);      // Lowbass area
            beatManager.AddBand(3, 6, 1.3f, 0.15f, 1.0f);      // Bass area
            beatManager.AddBand(6, 33, 1.3f, 0.15f, 1.0f);     // Lower Midrange area 
            beatManager.AddBand(33, 76, 1.3f, 0.15f, 1.0f);    // Upper Midrange area
            beatManager.AddBand(76, 131, 2.0f, 0.15f, 1.0f);   // presence area
            beatManager.AddBand(131, 256, 2.8f, 0.15f, 0.5f);  // treble area

            Components.Add(beatManager);
            beatManager.Enabled = false;

#if !XBOX
            spectrumAnalyzer = new SpectrumAnalyzer(this);
            Components.Add(spectrumAnalyzer);
            spectrumAnalyzer.Visible = false;
            spectrumAnalyzer.Enabled = false;
#endif

            frameBurst = new FrameBurst(this);
            Components.Add(frameBurst);
            frameBurst.Visible = false;
            frameBurst.Enabled = false;

            gameManager = new GameStateManager(this);
            Components.Add(gameManager);

            titleIntroState = new TitleIntroState(this);
            playingState = new PlayingState(this);
            pausedMenuState = new PausedMenuState(this);
            startMenuState = new StartMenuState(this);
            retryMenuState = new RetryMenuState(this);
            instructionsState = new InstructionsState(this);
            songOverState = new SongOverState(this);

            gameManager.ChangeState(titleIntroState.Value);
            base.Initialize();
        }

        protected override void LoadContent()
        {
            spriteBatch = new SpriteBatch(graphics.GraphicsDevice);
            arialFont = Content.Load<SpriteFont>(@"fonts\BerlinSmallCaps");
            base.LoadContent();
        }

        #endregion

        #region Update and Draw

        protected override void Update(GameTime gameTime)
        {

            if (gameManager.State == playingState.Value)
            {
                fpsProbe.CountFPS(gameTime);
            }
#if !XBOX
            if (input.WasPressed(Microsoft.Xna.Framework.Input.Keys.F11))
            {
                graphics.ToggleFullScreen();
            }
#endif

            base.Update(gameTime);
        }
      
        protected override void Draw(GameTime gameTime)
        {
#if !XBOX
            Vector2 positionScore = new Vector2(0, 0);
            Vector2 positionFPS = new Vector2(790, 0);
#else
            Vector2 positionScore = new Vector2(40, 40);
            Vector2 positionFPS = new Vector2(740, 40);
#endif
            if (gameManager.State == playingState.Value)
            {
                graphics.GraphicsDevice.Clear(Color.Black);
                spriteBatch.Begin();

                string message = string.Format(" FPS: {0}", this.fpsProbe.Count());
                spriteBatch.DrawString(arialFont, message, positionFPS, Color.White);

                spriteBatch.DrawString(arialFont, score.DisplayScore(), positionScore, Color.White);

                spriteBatch.End();
            }
            base.Draw(gameTime);
        }

        #endregion

        #region Entry Point

        static void Main()
        {
            using (RhythmCometGame game = new RhythmCometGame())
            {
                game.Run();
            }
        }

        #endregion

    }
}
